import pygame,pygame.locals
import sys,os,time

#   创建时间：  2021-05-22  21:32   by  炸天帮成员
#   将绿色方块的参数字典化，然后对象OBJECT化。这样可以将多余的全局变量整合到CLASS的self中去。
#   使用time来控制pygame的整体运行时间。
#   使用time来控制绿色方块出现的时间，这个时候需要添加 显示完成标志位(self.IRO_BLOCK_LOAD_STATE)来 判断 pygame.Rect对象是否正常显示 ，然后再进行移动该pygame.Rect对象。
#   若pygame.Rect对象已移出 pygame 窗口，则结束 显示，显示完成标志位(self.IRO_BLOCK_LOAD_STATE)将归为初始状态。
#   修改自  _6_pygame.demo_colorBlock_3_PNG_ExOK.py
#   及_8_pygame_demo_color_dictWithClass_0_ExOK.py

def game_init():
    pygame.init()
    pygame.display.init()

def refresh_pygame():                   #   这个refresh_pygame()函数要和 pygame.display.update() 一起结合使用。
                                        #   这样程序才不会运行至一半导致崩溃，另外仅有move_ip()而无blit()，也会导致图片不会刷新。
    FPS = 60
    pygame.time.Clock().tick(FPS)
    for event in pygame.event.get():
        if event.type == pygame.locals.QUIT:
            pygame.quit()
            sys.exit()
    DISPLAYSURF.blit(BKG_IMAGE,(0,0))   #   即背景图片的图层最先刷新，因为后出的blit()加载图片 会覆盖上一个blit()加载图片
                                        #   如果将此处注释掉 ， 则 那几个 IRO_BLOCK 中的 move() 会产生拖影。
                                        #   如果将背景图片的刷新给放入IRO_BLOCK的load()中，就会出现只显示 最后的blit()加载图片
COLOR_BLACK = (0,0,0)
COLOR_WHITE = (255,255,255)
COLOR_BKG = COLOR_BLACK

WORKPLACE_PATH = os.getcwd()
IMAGE_PATH = f'{WORKPLACE_PATH}\COLOR_BLOCK_PNG\\'

WINDOW_X_MAX = 400
WINDOW_Y_MAX = 400
DISPLAYSURF = pygame.display.set_mode((WINDOW_X_MAX,WINDOW_Y_MAX))
DISPLAYSURF.fill(COLOR_BKG)
BKG_IMAGE = pygame.image.load(IMAGE_PATH + 'whiteBKG.png')

GREEN_BLOCK_DICT = {            #   原始绿色方块字典的样式
    '0':{
        'ID':0,
        'TYPE':'GREEN_BLOCK',
        'NAME':'GREEN_BLOCK_0',
        'ALIVE_STATUS':False,
        'X_SIZE':40,
        'Y_SIZE':40,
        'START_POSITION':(WINDOW_X_MAX,WINDOW_Y_MAX/2),
        'MOVE_STEP':-5,
        'IMAGE':pygame.image.load(IMAGE_PATH + 'greenBlock.png'),
        'IRO_BLOCK_LOAD_STATE':False,   #   当CREATE_JIKANN参数不为None时，用于判断IRO_BLOCK 这个CLASS中的blit()是否正常被调用了。若正常被调用，则设置为True。
        'CREATE_JIKANN':None            #   即绿色方块出现的时间点，该时间点相对于PYGAME_START_TIME，单位为s。为None时，即从程序开始运行就出现（即理论上等同于值为0，但实际上还是有时间差的）。

    }
}

class IRO_BLOCK(pygame.sprite.Sprite):
    def __init__(self,BLOCK_ID,BLOCK_TYPE,BLOCK_NAME,\
                      BLOCK_ALIVE_STATUS,BLOCK_X_SIZE,BLOCK_Y_SIZE,\
                      BLOCK_START_POSITION,BLOCK_MOVE_STEP,BLOCK_IMAGE,\
                      BL_IRO_BLOCK_LOAD_STATE = False,BLOCK_CREATE_JIKANN = None):
        super().__init__()
        self.ID = BLOCK_ID
        self.TYPE = BLOCK_TYPE
        self.NAME = BLOCK_NAME
        self.ALIVE_STATUS = BLOCK_ALIVE_STATUS
        self.X_SIZE = BLOCK_X_SIZE
        self.Y_SIZE = BLOCK_Y_SIZE
        self.START_POSITION = BLOCK_START_POSITION
        self.MOVE_STEP = BLOCK_MOVE_STEP
        self.IMAGE = BLOCK_IMAGE
        self.IRO_BLOCK_LOAD_STATE = BL_IRO_BLOCK_LOAD_STATE     #   用于控制 显示的同时并移动的 标志位。True 即为 显示的同时并移动pygame.Rect对象；False 即为报错，未加载图片。当然False也可以改为 不显示（隐身）的同时并移动pygame.Rect对象，见[F0]。
        self.CREATE_JIKANN = BLOCK_CREATE_JIKANN                #   即绿色方块出现的时间点，该时间点相对于PYGAME_START_TIME，单位为s。为None时，即从程序开始运行就出现（即理论上等同于值为0，但实际上还是有时间差的）。
        print('self.CREATE_JIKANN = ',self.CREATE_JIKANN)

        self.SURF = pygame.Surface((self.X_SIZE,self.Y_SIZE))
        self.RECT = self.SURF.get_rect(center = self.START_POSITION)

    def load(self):
        global PYGAME_START_TIME
        if self.CREATE_JIKANN == None :
            DISPLAYSURF.blit(self.IMAGE,self.RECT)
            self.IRO_BLOCK_LOAD_STATE = True    #   self.IRO_BLOCK_LOAD_STATE 用于控制 move()   中的pygame.Rect是否真的需要 同时显示并移动。
        else :
            #   下面这个 if 用于在 规定的时间内 第一次显示 绿色方块。
            if self.CREATE_JIKANN < time.time() - PYGAME_START_TIME < self.CREATE_JIKANN + 1 and self.IRO_BLOCK_LOAD_STATE == False :   #   time.time() - PYGAME_START_TIME 需要一个范围值才能被使用，因为计算结果本身是个浮点数。
                DISPLAYSURF.blit(self.IMAGE,self.RECT)
                self.IRO_BLOCK_LOAD_STATE = True
                print('绿色方块刚出现时的时间 : ',time.ctime(time.time()))
                print('绿色方块刚出现时的self.RECT.left = ',self.RECT.left)
            #   下面这个elif    意味着即当该pygame.Rect依旧存活时，显示pygame.Rect对象
            elif self.IRO_BLOCK_LOAD_STATE == True :
                DISPLAYSURF.blit(self.IMAGE,self.RECT)
                print('绿色方块的时间 : ',time.ctime(time.time()))
                print('绿色方块的self.RECT.left = ',self.RECT.left)

    def move(self):
        if self.IRO_BLOCK_LOAD_STATE == True :  #   即  load()函数已被调用，需要 同时显示pygame.Rect对象并移动该pygame.Rect对象。
            self.RECT.move_ip(self.MOVE_STEP,0)
            if self.RECT.right < 0 :        #   可以从 self.ALIVE_STATUS 和 self.IRO_BLOCK_LOAD_STATE 的赋值状态可以看出，本文件中，这两个状态值的含义是差不多的，即都代表着 需要显示并移动的 绿色方块 的 生存状态。
                                            #   只不过 本文件中使用 self.IRO_BLOCK_LOAD_STATE 来控制 load() 和 move() 的状态。
                self.ALIVE_STATUS = False   #   如果绿色方块移出pygame的窗口，则设定该绿色方块已死亡。
                self.IRO_BLOCK_LOAD_STATE = False   #   绿色方块死亡，即意味着load()函数的标志位 回归 False
            else :
                self.ALIVE_STATUS = True    #   如果绿色方块未移出pygame的窗口，则设定该绿色方块存活。
                self.IRO_BLOCK_LOAD_STATE = True    #   绿色方块存活，即意味着load()函数的标志位 保持 True
        else :
            print(f'{self.NAME}图像未被{self.NAME}.load()!')
            #self.RECT.move_ip(self.MOVE_STEP,0)                                #[F0]    若开启这行，则意味着，需要 不显示（隐身）pygame.Rect对象的同时 移动该pygame.Rect对象。即不显示pygame.Rect对象的时候，该pygame.Rect对象也会发生移动。
                                                                                #[F0]    需要再做修改才能满足上一行的这句话，因为设定self.CREATE_JIKANN后，一开始pygame.Rect对象由于[F0]开启，也是在移动的，所以导致在需要显示该pygame.Rect对象的时刻时，
                                                                                #[F0]    该pygame.Rect对象已经被移出pygame的窗口了(从Terminal的运行结果可以看出来)，所以可以通过加上time限制或pygame.Rect.left或者right的限定或者添加load()被调用的次数
                                                                                #[F0]    来实现该 隐身的同时并移动的 函数功能。
            #print('self.IRO_BLOCK_LOAD_STATE = ',self.IRO_BLOCK_LOAD_STATE)    #[F1]    若关闭[F0], 则意味着当前程序只在 pygame.Rect对象显示的时候，该pygame.Rect对象才会发生移动。

# 以下4行用于测试   将字典中的条目  印射到  IRO_BLOCK   这个    CLASS中，并实例化(对象OBJECT化)
# GREEN_BLOCK_DICT['0'] = IRO_BLOCK(GREEN_BLOCK_DICT['0']['ID'],GREEN_BLOCK_DICT['0']['TYPE'],GREEN_BLOCK_DICT['0']['NAME'],\
#                     GREEN_BLOCK_DICT['0']['ALIVE_STATUS'],GREEN_BLOCK_DICT['0']['X_SIZE'],GREEN_BLOCK_DICT['0']['Y_SIZE'],\
#                     GREEN_BLOCK_DICT['0']['START_POSITION'],GREEN_BLOCK_DICT['0']['MOVE_STEP'],GREEN_BLOCK_DICT['0']['IMAGE'])
# print("GREEN_BLOCK_DICT['0'] = ",GREEN_BLOCK_DICT['0'],'\n类型为 ： ',type(GREEN_BLOCK_DICT['0']))

GREEN_BLOCK_MAX_NUMBER = 1              #   设置 最多有  GREEN_BLOCK_MAX_NUMBER  个绿色方块。使用时从下标0开始。
def NEW_GREEN_BLOCK_OBJ(BLOCK_MAX_NUMBER):
    for i in range (0,GREEN_BLOCK_MAX_NUMBER):
        GREEN_BLOCK_DICT[str(i)] = {
                                    'ID':i,
                                    'TYPE':'GREEN_BLOCK',
                                    'NAME':f'GREEN_BLOCK_{i}',
                                    'ALIVE_STATUS':False,
                                    'X_SIZE':40,
                                    'Y_SIZE':40,
                                    'START_POSITION':(WINDOW_X_MAX,WINDOW_Y_MAX/2),
                                    'MOVE_STEP':-5,
                                    'IMAGE':pygame.image.load(IMAGE_PATH + 'greenBlock.png'),
                                    'IRO_BLOCK_LOAD_STATE':False,
                                    'CREATE_JIKANN':2    #   即绿色方块出现的时间点，该时间点相对于PYGAME_START_TIME，单位为s。
                                    }
        GREEN_BLOCK_DICT[str(i)] = IRO_BLOCK(GREEN_BLOCK_DICT[str(i)]['ID'],GREEN_BLOCK_DICT[str(i)]['TYPE'],GREEN_BLOCK_DICT[str(i)]['NAME'],\
                    GREEN_BLOCK_DICT[str(i)]['ALIVE_STATUS'],GREEN_BLOCK_DICT[str(i)]['X_SIZE'],GREEN_BLOCK_DICT[str(i)]['Y_SIZE'],\
                    GREEN_BLOCK_DICT[str(i)]['START_POSITION'],GREEN_BLOCK_DICT[str(i)]['MOVE_STEP'],GREEN_BLOCK_DICT[str(i)]['IMAGE'],\
                    BL_IRO_BLOCK_LOAD_STATE = GREEN_BLOCK_DICT[str(i)]['IRO_BLOCK_LOAD_STATE'],BLOCK_CREATE_JIKANN = GREEN_BLOCK_DICT[str(i)]['CREATE_JIKANN'])
# 以下两行为测试    def NEW_GREEN_BLOCK_OBJ(BLOCK_MAX_NUMBER)   函数用。
# NEW_GREEN_BLOCK_OBJ(GREEN_BLOCK_MAX_NUMBER)
# print("GREEN_BLOCK_DICT = ",GREEN_BLOCK_DICT,'\nGREEN_BLOCK_DICT类型为 ： ',type(GREEN_BLOCK_DICT),'\nGREEN_BLOCK_DICT个数为 ：',len(GREEN_BLOCK_DICT))

if __name__ == "__main__":
    game_init()
    NEW_GREEN_BLOCK_OBJ(GREEN_BLOCK_MAX_NUMBER)
    print("GREEN_BLOCK_DICT = ",GREEN_BLOCK_DICT,'\nGREEN_BLOCK_DICT类型为 ： ',type(GREEN_BLOCK_DICT),'\nGREEN_BLOCK_DICT个数为 ：',len(GREEN_BLOCK_DICT))

    PYGAME_START_TIME = time.time()
    print('游戏启动时间为 : ',time.ctime(PYGAME_START_TIME))
    SET_PYGAME_RUNNING_TIME = 10                                         #   设定pygame的运行时间，单位为s
    while time.time()-PYGAME_START_TIME < SET_PYGAME_RUNNING_TIME :     #   使用time来控制pygame的整体运行时间。
        refresh_pygame()
        GREEN_BLOCK_DICT['0'].load()    #   注意若用于显示Rect对象的blit()未写，而只写move_ip()，则在后台中，pygame.Rect()对象是依旧在移动的，但不会被显示出来。
        GREEN_BLOCK_DICT['0'].move()    #   故要放弃以前的写法，使用类似于本程序中在blit()的包裹函数load()和move()两个函数上动手脚，这样才能在规定时间里显示并移动，而不是 不显示并移动。
                                        #   综上2行，即pygame()将这两个东西分开的原因是，显示归显示(使用blit)，pyugame.Rect对象移动归移动(使用move_ip)，
                                        #   若要在显示的同时并移动，则必须blit和move_ip同时被调用才行。具体见self.IRO_BLOCK_LOAD_STATE这个参数出现的地方。
        pygame.display.update()
        #print("GREEN_BLOCK_DICT['0']的生存状态 : ",GREEN_BLOCK_DICT['0'].ALIVE_STATUS)
    print('游戏结束时间为 : ',time.ctime(time.time()))
    print("绿色方块的GREEN_BLOCK_DICT['0'].RECT.left = ",GREEN_BLOCK_DICT['0'].RECT.left)


    #   总结：
    #       需要查看上一个版本的总结，
    #       同样也在_8_pygame_demo_color_dictWithClass_0_ExOK.py的最下方。
    #       关于本文件中的self.ALIVE_STATUS 和 self.IRO_BLOCK_LOAD_STATE 实际上是同一个东西，都是用来判断 绿色方块 是否需要 “继续显示然后移动”的。
    #       所以它们的初始化和终结时的标志位归位位置也相同。
    #       出现这个原因的原因是，self.ALIVE_STATUS为_8_pygame_demo_color_dictWithClass_0_ExOK.py中遗留下来的东西。
    #       而在解决 在某个时刻出现某个绿色方块后再移动的·问题时，是压根就没去考虑 self.ALIVE_STATUS，而是直接新起了个self.IRO_BLOCK_LOAD_STATE，
    #       所以才会出现 self.ALIVE_STATUS 和 self.IRO_BLOCK_LOAD_STATE 功能重复的问题。（self.ALIVE_STATUS可删）

    #       下一个版本中将解决
    #       每个绿色方块 将以 每秒多少STEP的速度移动 的问题。
    #       详见_8_pygame_demo_color_dictWithClass_2_Multi_TimeControl_ExOK.py
    #       思路就是，在Class的__init__()中添加一个self变量，用来储存该pygame.Rect对象上一次出现的time.time()
    #       然后使用 if 在move()中进行判断，且若当该 pygame.Rect对象 未移出pygame的窗口时，则该self变量将再次使用time.time()记录本次移动结束的时间 。